//go:build darwin

package collector

import (
	"os/exec"
	"strconv"
	"strings"

	"sysinfo/internal/types"
	"sysinfo/internal/utils"
)

func collectPhysicalDisksPlatform() []types.PhysicalDisk {
	disks := make([]types.PhysicalDisk, 0)

	// Check if diskutil is available
	if _, err := exec.LookPath("diskutil"); err != nil {
		return disks
	}

	// Get the list of whole disks
	cmd := exec.Command("diskutil", "list", "-plist")
	_, err := cmd.Output()
	if err != nil {
		return disks
	}

	// Parse plist output
	// Note: macOS uses plist format, but we'll use diskutil info and JSON for each disk
	// 首先，获取物理磁盘列表
	wholeDisks := getWholeDisks()

	for _, diskID := range wholeDisks {
		disk := getDiskInfo(diskID)
		if disk.Name != "" {
			disks = append(disks, disk)
		}
	}

	return disks
}

// getWholeDisks returns a list of whole disk identifiers
func getWholeDisks() []string {
	cmd := exec.Command("diskutil", "list")
	output, err := cmd.Output()
	if err != nil {
		return nil
	}

	disks := make([]string, 0)
	lines := strings.Split(string(output), "\n")

	for _, line := range lines {
		// 查找类似 "/dev/disk0 (internal, physical):" 的行
		if strings.Contains(line, "/dev/disk") && (strings.Contains(line, "physical") || strings.Contains(line, "external")) {
			parts := strings.Fields(line)
			if len(parts) > 0 {
				diskPath := strings.TrimSpace(parts[0])
				// 仅提取磁盘标识符（例如从 "/dev/disk0" 提取 "disk0"）
				diskID := strings.TrimPrefix(diskPath, "/dev/")
				disks = append(disks, diskID)
			}
		}
	}

	return disks
}

// getDiskInfo 获取特定磁盘的详细信息
func getDiskInfo(diskID string) types.PhysicalDisk {
	disk := types.PhysicalDisk{
		Name: "/dev/" + diskID,
	}

	// 使用带JSON输出的diskutil info（在较新macOS上可用）
	cmd := exec.Command("diskutil", "info", "-plist", diskID)
	output, err := cmd.Output()
	if err != nil {
		return disk
	}

	// 解析plist输出 - 我们将使用更简单的文本解析方法
	lines := strings.Split(string(output), "\n")
	for i, line := range lines {
		line = strings.TrimSpace(line)

		// Parse key-value pairs from plist
		if strings.Contains(line, "<key>MediaName</key>") && i+1 < len(lines) {
			modelLine := strings.TrimSpace(lines[i+1])
			disk.Model = extractPlistString(modelLine)
		} else if strings.Contains(line, "<key>TotalSize</key>") && i+1 < len(lines) {
			sizeLine := strings.TrimSpace(lines[i+1])
			if size := extractPlistInteger(sizeLine); size > 0 {
				disk.Size = size
				disk.SizeFormatted = utils.FormatBytes(size)
			}
		} else if strings.Contains(line, "<key>SolidState</key>") && i+1 < len(lines) {
			if strings.Contains(lines[i+1], "<true/>") {
				disk.Type = "SSD"
			} else {
				disk.Type = "HDD"
			}
		} else if strings.Contains(line, "<key>Protocol</key>") && i+1 < len(lines) {
			protocolLine := strings.TrimSpace(lines[i+1])
			protocol := extractPlistString(protocolLine)
			disk.Interface = strings.ToUpper(protocol)

			// 检测NVMe
			if strings.Contains(strings.ToUpper(protocol), "NVME") || strings.Contains(strings.ToUpper(protocol), "PCI") {
				disk.Type = "NVMe"
				disk.Interface = "NVMe"
			}
		} else if strings.Contains(line, "<key>Removable</key>") && i+1 < len(lines) {
			disk.Removable = strings.Contains(lines[i+1], "<true/>")
		} else if strings.Contains(line, "<key>Device / Media Name</key>") && i+1 < len(lines) {
			modelLine := strings.TrimSpace(lines[i+1])
			if disk.Model == "" {
				disk.Model = extractPlistString(modelLine)
			}
		}
	}

	// 如果类型仍然未知，尝试从磁盘名称检测
	if disk.Type == "" {
		if strings.HasPrefix(diskID, "disk") {
			// 通过system_profiler检查是否是SSD（较慢但更准确）
			if isSSD := checkSSDSystemProfiler(diskID); isSSD {
				disk.Type = "SSD"
			} else {
				disk.Type = "HDD"
			}
		}
	}

	return disk
}

// extractPlistString 从plist XML行中提取字符串值
func extractPlistString(line string) string {
	// 行格式如：<string>APPLE SSD AP0512R</string>
	line = strings.TrimPrefix(line, "<string>")
	line = strings.TrimSuffix(line, "</string>")
	return strings.TrimSpace(line)
}

// extractPlistInteger 从plist XML行中提取整数值
func extractPlistInteger(line string) uint64 {
	// 行格式如：<integer>512110190592</integer>
	line = strings.TrimPrefix(line, "<integer>")
	line = strings.TrimSuffix(line, "</integer>")
	line = strings.TrimSpace(line)
	if val, err := strconv.ParseUint(line, 10, 64); err == nil {
		return val
	}
	return 0
}

// checkSSDSystemProfiler 使用system_profiler检查磁盘是否为SSD（回退方案）
func checkSSDSystemProfiler(_ string) bool {
	cmd := exec.Command("system_profiler", "SPSerialATADataType", "-json")
	output, err := cmd.Output()
	if err != nil {
		return false
	}

	// 简单检查 - SSD通常在输出中包含"Solid State"
	return strings.Contains(string(output), "Solid State")
}
